#include"mystdio.h"


MY_FILE* _fopen(const char* path_name, const char* mode)
{
    int flags = 0;
    if(strcmp(mode, "r") == 0)
    {
        flags |= O_RDONLY;
    }
    else if(strcmp(mode, "w") == 0)
    {
        flags |= O_WRONLY | O_CREAT | O_TRUNC;
    }
    else if(strcmp(mode, "a") == 0)
    {
        flags |= O_WRONLY | O_CREAT | O_APPEND;
    }
    else
    {
        // 其他情况不处理
    }

    int fd = 0;
    // 要注意open在创建文件的时候要传入起始权限
    if(flags & O_RDONLY)
        fd = open(path_name, flags);
    else
        fd = open(path_name, flags, 0666);

    if(fd < 0)
    {
        const char* err = strerror(errno);
        write(2, err, strlen(err));
        return NULL; //fopen打开文件失败会返回NULL
    }

    MY_FILE* fp = (MY_FILE*)malloc(sizeof(MY_FILE));
    assert(fp != NULL);
    //fp->flag = SYNC_NOW; //默认设置成无缓冲
    fp->flag = SYNC_LINE; //默认设置成行缓冲
    fp->fileno = fd;
    fp->cap = SIZE;
    fp->size = 0;
    memset(fp->buffer, 0, SIZE);

    return fp;
}

void _fwrite(const void* ptr, int num, MY_FILE* fp)
{
    // 先将数据写入缓冲区
    memcpy(fp->buffer+fp->size, ptr, num); // 这里不考虑缓冲区溢出的情况
    fp->size += num;
    
    // 这里就要判断当前的刷新策略是什么
    if(fp->flag == SYNC_NOW)
    {
        // 无缓冲
        write(fp->fileno, fp->buffer, fp->size); // 将缓冲区的内容输出到fp当中找到的指定文件
        fp->size = 0;
    }
    else if(fp->flag == SYNC_FULL)
    {
        // 全缓冲
        if(fp->cap == fp->size)
        {
            // 当缓冲区满了之后，就进行刷新
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;
        }
    }
    else if(fp->flag == SYNC_LINE)
    {
        //行缓冲
        if(fp->buffer[fp->size - 1] == '\n') // 不考虑abcd\naaa 的这种情况
        {
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;
        }
    }
    else
    {
        // 有问题
    
    }


}

void _fflush(MY_FILE* fp)
{
    assert(fp);

    write(fp->fileno, fp->buffer, fp->size);
    fp->size = 0;  
    fsync(fp->fileno); //强制OS将数据写入到文件中
}

void _fclose(MY_FILE* fp)
{
    assert(fp);

    // 关闭文件之前要把缓冲区给刷新
    _fflush(fp);
    close(fp->fileno); 
}


